var slideStreamId;

var slideList = {
		
	currentSlide: null,
	thumbnailLoaderPeriodical: null,
	savePeriodical: null,
	
	init : function(settings) {
		slideList.config = {
		    $parent              : $('#timelineThumbs'),
			baseUrl              : $('#baseUrl').val(),
			thumbSelector        : 'div.thumbnail',
			thumbnailLoaderTimer : 15, // how often to check to load the thumbnails
			saveTimer            : 30  // it'll run more frequently than this when the user is doing things, but this is just in case.
		};
	
		// allow overriding the default config
		$.extend(slideList.config, settings);
		
		slideList.config.$parent.sortable({
			axis: 'y',
			containment: 'parent',
			tolerance: 'pointer',
			stop: function(event, ui) {
				slideList.updateSlideOrder();
				slideList.save();
			}
		});
		
		// when a user clicks on a slide thumbnail, we'll load all the data
		// associated with that slide into the correct places
		// for any modules, it assumes that the keys are mapped to id's			
		$(slideList.config.thumbSelector, slideList.config.$parent).live('click', function(e) {
			
			var $obj = $(this);
			
			slideList.currentSlide = $obj;
			
			$(slideList.config.thumbSelector).removeClass('selected');
			$obj.addClass('selected');
			
			var slideId = $obj.data('slideId');
			
			if (!$obj.hasClass('loading')) {
				previewPane.setImage(slideId);
			} else {
				previewPane.setImage(false);
			}
			
			previewPane.setTitle($obj.data('title'));
		    previewPane.setUrl($obj.data('url'));
			previewPane.setDisplayLength($obj.data('displayLength'));
			
			// load module data for the slide if it exists
			controlPanel.getModules().each(function() {
				
				var module = $(this);
				var moduleName = module.attr('id');		

				var moduleData = $obj.data(moduleName);
				
				if (moduleData != undefined && moduleData.length != 0) {
					// we assume that there is an element with the same id in the module DOM element to dump the data into
					$.each(moduleData, function(index, el) {
						$('#' + index, module).val(el);
					});
				} else {
					// if there is no data for the module for this slide, then just empty the fields
					$(this).find('input[type=text], textarea, input[type=radio], select').val('');
				}
			});
		});
				
		// the periodical starts here, the * 1000 is because milliseconds are required
		slideList.thumbnailLoaderPeriodical = window.setInterval(slideList.loadThumbnailScreenshots, slideList.config.thumbnailLoaderTimer * 1000);
		
		// the periodical starts here, the * 1000 is because milliseconds are required
		slideList.savePeriodical = window.setInterval(slideList.save, slideList.config.saveTimer * 1000);
	},
	
	loadSlides: function() {
		
		// get all the entities for the timeline
		$.ajax({
		    url: slideList.config.baseUrl + '/slidestream/index/get-entities?slideStreamId=' + slideStreamId,
		    type: 'GET',
		    dataType: 'json',
		    async: false,
		    success: function(data, textStatus) {
				$.each(data, function(index, el) {
					var thumb = slideList.createThumbnailElement(el.data.slideId, el.data.title, el.data.url, el.displayLength);
					
					// store the data for the modules into the object
					$.each(el.moduleData, function(name, data) {
						thumb.data(name, data);
					});
					
					slideList.addSlideToList(thumb);
				});
			}
		});
		
		slideList.updateSlideOrder();
		slideList.loadThumbnailScreenshots();
		infoPane.updateTotals();
		
		slideList.config.$parent.find(slideList.config.thumbSelector + ':first').click();
	},
	
	addSlideToList: function(slideObj) {
		slideList.config.$parent.prepend(slideObj);
	},
	
	/**
	 * Creates a thumbnail element.  All the data for the slide is stored with
	 * this object
	 * 
	 * @param slideId The slideId of the slide
	 * @param title The title of the slide
	 * @param url The url that the slide points to
	 * @param displayLength The number of seconds to display the slide
	 * @return The thumbnail object
	 */
	createThumbnailElement: function(slideId, title, url, displayLength) {
		
	    var newThumb = $('<div></div>').addClass('thumbnail').addClass('loading');
	    newThumb.append($('<div></div>').addClass('displayLength').text(UTIL.formatTime(displayLength, true)));
	    newThumb.append($('<div></div>').addClass('title').text(title));
	    
	    newThumb.data('slideId', slideId);
	    newThumb.data('title', title);
	    newThumb.data('url', url);
	    newThumb.data('displayLength', displayLength);
	    
	    return newThumb;
	},
	
	updateSlideOrder: function() {
		var tmpOrder = 1;
		$(slideList.config.thumbSelector, slideList.config.$parent).each(function() {
			$(this).data('order', tmpOrder++);
		});
	},
	
	/**
	 * Saves the slidestream.  It will just return if it's already in progress.  Creates
	 * a JSON string representing the data structure with all it's attributes and any
	 * module info associated with it to send to the backend.
	 */
	save: function() {
		
		if (infoPane.isSaveDisabled() == true) {
			return;
		}
		
		infoPane.disableSave();
				
		var slideListArray = [];

		var i = 0;
		$(slideList.config.thumbSelector, slideList.config.$parent).each(function() {
			
			var $obj = $(this);
						
			slideListArray[i] = {
				slideId       : $obj.data('slideId'),
				order         : $obj.data('order'),
				url           : $obj.data('url'),
				title         : $obj.data('title'),
				displayLength : $obj.data('displayLength'),
				moduleData    : slideList.getAllModuleData($obj)
			};
			
			i++;
		});
		
		var structureStr = $.toJSON(slideListArray);
	    
	    $.post(
	    		slideList.config.baseUrl + '/slidestream/index/save-slide-stream',
	    		{
	    			slideStreamId: slideStreamId,
	    			data:          structureStr
	    		},
	    		function(data, textStatus) {
	    			if (data.rc == 1) {
	    				
	    			} else {
	    				alert(data.msg);
	    			}
	    			
	    			infoPane.enableSave();
	    		},
	    		'json'
	    	  );
	},
	
	getAllModuleData: function($obj) {
		
		var moduleData = {};
		
		controlPanel.getModules().each(function() {
			
			var moduleName = $(this).attr('id');
			
			if ($obj.data(moduleName) != undefined) {
				moduleData[moduleName] = $obj.data(moduleName);
			}
		});
		
		return moduleData;
	},
	
	getCurrentSlide: function() {
		return slideList.currentSlide;
	},
	
	getCurrentSlideId: function() {
		
		if (slideList.currentSlide == null) {
			return null;
		}
		
		return slideList.currentSlide.data('slideId');
	},
	
	getCurrentSlideTitle: function() {
		
		if (slideList.currentSlide == null) {
			return null;
		}
		
		return slideList.currentSlide.data('title');
	},
	
	getCurrentSlideUrl: function() {
		
		if (slideList.currentSlide == null) {
			return null;
		}
		
		return slideList.currentSlide.data('url');
	},
	
	getCurrentSlideDisplayLength: function() {
		
		if (slideList.currentSlide == null) {
			return null;
		}
		
		return slideList.currentSlide.data('displayLength');
	},
	
	setCurrentSlideTitle: function(title) {
		slideList.currentSlide.data('title', title);
		slideList.currentSlide.find('div.title').text(title);
	},
	
	setCurrentSlideUrl: function(url) {
		slideList.currentSlide.data('url', url);
	},
	
	setCurrentSlideDisplayLength: function(displayLength) {
		slideList.currentSlide.data('displayLength', displayLength);
		slideList.currentSlide.find('div.displayLength').text(UTIL.formatTime(displayLength, true));
	},
	
	getTotalRunningTime: function() {
		var totalRunningTimeValue = 0;
		$(slideList.config.thumbSelector, slideList.config.$parent).each(function() {
			totalRunningTimeValue += parseInt($(this).data('displayLength'), 10);
		});
		
		return totalRunningTimeValue;
	},
	
	getSlideCount: function() {
		return $(slideList.config.thumbSelector, slideList.config.$parent).length;
	},
	
	setModuleData: function(moduleName, moduleData) {
		slideList.currentSlide.data(moduleName, moduleData);
	},
	
	getModuleData: function(moduleName) {
		return slideList.currentSlide.data(moduleName);
	},
	
	/**
	 * Loads the thumbnail images
	 */
	loadThumbnailScreenshots: function() {
		
		$('div.loading', slideList.config.$parent).each(function() {
						
			var $obj = $(this);
			
			$obj.css('backgroundImage', 'url(' + slideList.config.baseUrl + '/public/images/slideThumbDefault.png');
			
			var slideId = $obj.data('slideId');
			var imagePath = baseUrl + '/public/screenshots/' + slideId + '/thumbnail.jpg';
			
			$.getJSON(slideList.config.baseUrl + '/slidestream/index/screenshots-exist?slideId=' + slideId, function(data, textStatus) {
				
				if (data.result == "1") {
					$obj.css('backgroundImage', 'url(' + imagePath + ')');
					
					if (slideId == slideList.getCurrentSlideId()) {
						previewPane.setImage(slideId);
					}
					
					$obj.removeClass('loading');
				} else {
					// make the request to generate the screenshots
					$.ajax({
						type: 'GET',
					    url: slideList.config.baseUrl + '/slidestream/index/generate-screenshots',
					    data: 'slideId=' + slideId,
					    async: true,
					    beforeSend: function(XMLHttpRequest) {
							if ($obj.data('running') == true) {
								return false;
							} else {
								$obj.data('running', true);
							}
						},
						complete: function(XMLHttpRequest, textStatus) {
							$obj.removeData('running');
						},
						
					});
				}
			});
		});
	},
	
	deleteCurrent: function() {
		var next = slideList.currentSlide.next();
		var prev = slideList.currentSlide.prev();
				
		$.post(
			slideList.config.baseUrl + '/slidestream/index/delete-slide',
			{
				slideStreamId: slideStreamId,
				slideId: slideList.currentSlide.data('slideId')
			},
			function(data, textStatus) {
				if (data.rc == 1) {
					
					slideList.currentSlide.remove();
					if (next.length != 0) {
						next.click();
					} else if (prev.length != 0) {
						prev.click();
					} else {
						// don't try to select another slide
					}
					
					slideList.updateSlideOrder();
					infoPane.updateTotals();
					slideList.save();
				} else {
					alert('Error deleting slide.  Please try again');
				}
			},
			'json'
	    );
	}
};

var infoPane = {
		
	$totalSlides : null,
	$totalRunningTime : null,
	$saveSlideStreamButton : null,
	$addSlideButton : null,
	$dialog : null,
	$slideStreamTitle : null,
		
	init: function(settings) {
		infoPane.config = { 
			baseUrl : $('#baseUrl').val(),
			slideForm : '#slideForm'
		}
		
		infoPane.$totalSlides           = $('#totalSlides');
		infoPane.$totalRunningTime      = $('#totalRunningTime');
		infoPane.$saveSlideStreamButton = $('#saveSlideStreamButton');
		infoPane.$addSlideButton        = $('#addSlideButton');
		infoPane.$dialog                = $('#dialog');
		infoPane.$slideStreamTitle      = $('span#slideStreamTitle');
		
		infoPane.$saveSlideStreamButton.click(function(e) {
			slideList.save();
		});
		
		infoPane.$addSlideButton.click(function() {
			infoPane.$dialog.load(infoPane.config.baseUrl + '/slide/index/add?slideStreamId=' + slideStreamId, function() {
				infoPane.handleAddForm();
				
			}).dialog({
				bgiframe: true,
				height: 200,
				width: 375,
				modal: true,
				title: 'Add New Slide'
			});
		});
		
		infoPane.$slideStreamTitle.hover(
			function(){ $(this).addClass('ui-state-highlight'); }, 
			function(){ $(this).removeClass('ui-state-highlight'); }
			
		).click(function() {
			var newSlideStreamTitle = prompt('Enter the new slide stream title:', $(this).text());
			
			if ($.trim(newSlideStreamTitle) != "") {
						
				$(this).text(newSlideStreamTitle);
				$.post(infoPane.config.baseUrl + '/slidestream/index/save-slide-stream-info',
				   {
				      slideStreamId: slideStreamId,
				      title        : newSlideStreamTitle
				   },
				   function(data, textStatus) {
				   },
				   'json');
			}
		});
	},
	
	isSaveDisabled: function() {
		return	infoPane.$saveSlideStreamButton.attr('disabled');
	},
	
	disableSave: function() {
		infoPane.$saveSlideStreamButton.attr('disabled', true)
					  				   .addClass('ui-state-disabled')
									   .val('Saving...');
	},
	
	enableSave: function() {
		infoPane.$saveSlideStreamButton.attr('disabled', false)
							 		   .removeClass('ui-state-disabled')
									   .val('Save Slide Stream');
	},
	
	updateTotals: function() {
		
		var totalRunningTimeValue = slideList.getTotalRunningTime();
		var totalSlidesValue = slideList.getSlideCount();
			
		infoPane.$totalRunningTime.text(UTIL.formatTime(totalRunningTimeValue));
		infoPane.$totalSlides.text(totalSlidesValue);
		
		if (totalSlidesValue == 0) {
			previewPane.hide();
			controlPanel.hide();
		} else {
			previewPane.show();
			controlPanel.show();
		}
	},
	
	handleAddForm: function() {
		
		$('#title', $(infoPane.config.slideForm)).focus();
		
		UTIL.themeButtons($(infoPane.config.slideForm));
		
		$(infoPane.config.slideForm).find('button#cancel').click(function() {
			infoPane.$dialog.dialog('destroy');
		});
		
		$(infoPane.config.slideForm).submit(function() { 
	        // inside event callbacks 'this' is the DOM element so we first 
	        // wrap it in a jQuery object and then invoke ajaxSubmit 
	        $(this).ajaxSubmit({
	        	target:        '#dialog',    // target element(s) to be updated with server response,
	            success: function(responseText, statusText) {
	        		if (parseInt(responseText)) { // the responseText will be the new slideId if successful
	        			infoPane.$dialog.dialog('destroy');
	        			
	        			$.getJSON(infoPane.config.baseUrl + '/slide/index/get-slide-info?slideId=' + responseText, function(data, statusText) {
	        				
	        				var newThumb = slideList.createThumbnailElement(data.slideId, data.title, data.url, 5);
	            			slideList.addSlideToList(newThumb);
	            			
	            			if (slideList.getSlideCount() == 1) {
	            				newThumb.click();
	            			}
	            			
	            			infoPane.updateTotals();
	            			slideList.updateSlideOrder();
	            			slideList.save();
	            			slideList.loadThumbnailScreenshots();
	        			});
	        		} else {
	        			infoPane.handleAddForm(); 			
	        		}
	        	}
	        });
	 
	        return false; 
	    });
	}
};

var controlPanel = {
	
	init : function(settings) {
	
		controlPanel.config = {
			baseUrl  : $('#baseUrl').val(),
			$content : $('#controlPanel')
		}
		
		$.extend(controlPanel.config, settings);
		
		controlPanel.config.$content.accordion({});
	},
	
	getModules: function() {
		return $('div.module', controlPanel.config.$content);
	},
	
	show: function() {
		controlPanel.config.$content.css('visibility', 'visible');
	},
	
	hide: function() {
		controlPanel.config.$content.css('visibility', 'hidden');
	}

};

var previewPane = {
	
	$image             : null,
	$content           : null,
	$title             : null,
	$url               : null,
	$previewLink       : null,
	$displayLength     : null,
	$minutesSlider     : null,
	$secondsSlider     : null,
	$deleteSlideButton : null,
	$dialog            : null,
		
	init : function(settings) {
	
		previewPane.config = {
			baseUrl : $('#baseUrl').val()
		};
		
		previewPane.$image             = $('#previewImage');
		previewPane.$content           = $('#previewPaneContent');
		previewPane.$title             = $('span#previewInfoTitle');
		previewPane.$url               = $('span#previewInfoUrl');
		previewPane.$previewLink       = $('span#previewLink');
		previewPane.$displayLength     = $('#displayLength');
		previewPane.$minutesSlider     = $('#displayMinutesSlider');
		previewPane.$secondsSlider     = $('#displaySecondsSlider');
		previewPane.$deleteSlideButton = $('#deleteSlideButton');
		
		previewPane.$dialog = $('<div><iframe></iframe></div>').insertAfter(previewPane.$previewLink);
		previewPane.$dialog.css('display', 'none');
		
		previewPane.$dialog.find('iframe')
	      .css({
	    	  width: '960px',
	    	  height: '640px',
	    	  border: '0'
	    });
		
		previewPane.$dialog.dialog({
			bgiframe: true,
			modal: true,
			resizeable: false,
			width: 970,
			height: 650,
			autoOpen: false,
			buttons: {
				Ok: function() {
					$(this).dialog('close');
				}
			}
		 });

		// allow overriding the default config
		$.extend(previewPane.config, settings);
		
		$(previewPane.$title).hover(
			function(){ $(this).addClass('ui-state-highlight'); }, 
			function(){ $(this).removeClass('ui-state-highlight'); }
		);
		
		previewPane.$deleteSlideButton.click(function(e) {
			slideList.deleteCurrent();
		});
		
		$(previewPane.$url).hover(
			function(){ $(this).addClass('ui-state-highlight'); }, 
			function(){ $(this).removeClass('ui-state-highlight'); }
		);
		
		previewPane.$title.click(function() {
			var newTitle = prompt('Enter the new title:', slideList.getCurrentSlideTitle());
			if ($.trim(newTitle) != "") {
				slideList.setCurrentSlideTitle(newTitle);
				previewPane.setTitle(newTitle);
				slideList.save();
			}
		});
		
		previewPane.$url.click(function() {
			var newUrl = prompt('Enter the new URL:', slideList.getCurrentSlideUrl());
			if ($.trim(newUrl) != "") {
				slideList.setCurrentSlideUrl(newUrl);
				previewPane.setUrl(newUrl);
				slideList.save();
			}
		});
		
		previewPane.$previewLink.click(function() {
			
			previewPane.$dialog.find('iframe').attr('src', slideList.getCurrentSlideUrl());
			
			var title = slideList.getCurrentSlideTitle();

			if (title.length > 140) {
				title = title.substring(0, 140) + '...';
			}
			
			previewPane.$dialog.dialog('option', 'title', title);
			previewPane.$dialog.dialog('open');
		});
		
		// setup display length sliders
		previewPane.$minutesSlider.slider({
			range: 'min',
			min: 0,
			max: 59,
			slide: function(event, ui) {
				var seconds = parseInt(previewPane.$secondsSlider.slider('value'), 10);
				var minutes = ui.value;
				previewPane.$displayLength.text(UTIL.formatTime(parseInt((minutes * 60) + seconds, 10)));
			},
			stop: function(event, ui) {
				var seconds = parseInt(previewPane.$secondsSlider.slider('value'), 10);
				var minutes = ui.value;
				slideList.setCurrentSlideDisplayLength((minutes * 60) + seconds);
				infoPane.updateTotals();
				slideList.save();
			}
		});	
	
		previewPane.$secondsSlider.slider({
			range: "min",
			min: 0,
			max: 59,
			slide: function(event, ui) {
				var minutes = parseInt(previewPane.$minutesSlider.slider('value'), 10);
				var seconds = parseInt(ui.value);
				previewPane.$displayLength.text(UTIL.formatTime(parseInt((minutes * 60) + seconds, 10)));
			},
			stop: function(event, ui) {
				var minutes = parseInt(previewPane.$minutesSlider.slider('value'), 10);
				var seconds = parseInt(ui.value);
				slideList.setCurrentSlideDisplayLength((minutes * 60) + seconds);
				infoPane.updateTotals();
				slideList.save();
			}
		});
	},
	
	setImage: function(slideId) {
		if (slideId === false) {
			previewPane.$image.css('backgroundImage', 'url(' + previewPane.config.baseUrl + '/public/images/slidePreviewDefault.png');
		} else {
			previewPane.$image.css('backgroundImage', 'url(' + previewPane.config.baseUrl + '/public/screenshots/' + slideId + '/preview.jpg)');
		}
	},
	
	setTitle: function(title) {
		if (title.length > 50) {
			title = title.substring(0, 50) + '...';
		}
		previewPane.$title.text(title);
	},
	
	setUrl: function(url) {
		if (url.length > 50) {
			url = url.substring(0, 50) + '...';
		}
		previewPane.$url.text(url);
	},
	
	setDisplayLength: function(displayLength) {
		
		var minutes = parseInt(parseInt(displayLength, 10) / 60, 10);
	    var seconds = parseInt(displayLength, 10) % 60;
		
		previewPane.$minutesSlider.slider('value', minutes);
		previewPane.$secondsSlider.slider('value', seconds);
		previewPane.$displayLength.text(UTIL.formatTime(displayLength));
	},
	
	hide: function() {
		previewPane.$content.css('visibility', 'hidden');
	},
	
	show: function() {
		previewPane.$content.css('visibility', 'visible');
	}
};

$(document).ready(function() {

	slideStreamId = $('#slideStreamId').val();
	
	slideList.init();
	previewPane.init();
	infoPane.init();
	controlPanel.init();
	
	slideList.loadSlides(); // load the slides after the interface has been setup

    /**
     * Initialize the modules we want to use
     */
    scheduleModule.init();
});


/**
 * Various utilities that are used by multiple objects
 */
var UTIL = {
		
		/**
		 * Adds the hover classes and round corners to newly created buttons
		 */
		themeButtons: function(scope) {

			var scope = $(scope);
			$('input[type=submit], input[type=button], input[type=reset], button', scope).addClass('ui-state-default ui-corner-all');
			$('a.ui-state-default, input.ui-state-default, button.ui-state-default', scope).hover(
				function(){ $(this).addClass('ui-state-hover'); }, 
				function(){ $(this).removeClass('ui-state-hover'); }
		  	);
		},

		/**
		 * Returns a string like "1 minute 40 seconds" given a number of seconds, or
		 * if the short param is set to true it will return a shortened version like
		 * "1m40s"
		 * 
		 * @param int|string seconds The number of seconds to format
		 * @param bool If true returns format like 1m2s
		 */
		formatTime: function(seconds, short) {
			
			var short = short || false;
			
			var seconds = parseInt(seconds, 10);
			
			var mins = parseInt(seconds / 60, 10);
			var secs = parseInt(seconds % 60, 10);
			
			var minsUnit = ' minutes ';
			var secsUnit = ' seconds';
			
			if (mins == 1) {
				minsUnit = ' minute ';
			}
			
			if (secs == 1) {
				secsUnit = ' seconds';
			}
			
			if (short == true) {
				minsUnit = 'm';
				secsUnit = 's';
			}
			
			return mins + minsUnit + secs + secsUnit;
		} 
};


/**
 * Sets up the all the interaction for the schedule module
 * 
 * All interaction with the module will operate on the data for the currentSlide
 */
var scheduleModule = {

	init : function(settings) {
	
		scheduleModule.config = {
			baseUrl      : $('#baseUrl').val(),
			moduleName   : 'Slide_Option_Schedule_Module',
			fromDate     : 'input#fromDate',
			toDate       : 'input#toDate',
			fromHour     : 'select#fromHour',
			fromMinute   : 'select#fromMinute',
			fromMeridian : 'select#fromMeridian',
			toHour       : 'select#toHour',
		    toMinute     : 'select#toMinute',
		    toMeridian   : 'select#toMeridian'
		}
		
		$.extend(scheduleModule.config, settings);
		
		$(scheduleModule.config.fromDate + ', ' + scheduleModule.config.toDate).datepicker({
			onClose: function(dateText, inst) {
				scheduleModule.updateTimes();
			}
		});
		
		$(scheduleModule.config.fromHour     + ', ' + 
		  scheduleModule.config.fromMinute   + ', ' + 
		  scheduleModule.config.fromMeridian + ', ' + 
		  scheduleModule.config.toHour       + ', ' + 
		  scheduleModule.config.toMinute     + ', ' +
		  scheduleModule.config.toMeridian).change(function() {
			scheduleModule.updateTimes();
		});
	},
	
	updateTimes : function() {
		
		var moduleData = {
				fromDate     : $(scheduleModule.config.fromDate).val(),
				toDate       : $(scheduleModule.config.toDate).val(),
				fromHour     : $(scheduleModule.config.fromHour).val(),
				fromMinute   : $(scheduleModule.config.fromMinute).val(),
				fromMeridian : $(scheduleModule.config.fromMeridian).val(),
				toHour       : $(scheduleModule.config.toHour).val(),
				toMinute     : $(scheduleModule.config.toMinute).val(),
				toMeridian   : $(scheduleModule.config.toMeridian).val()
		}
		
		slideList.setModuleData(scheduleModule.config.moduleName, moduleData);
		slideList.save();
	}
}